import { CSMesh, KeepSizeObject3D, SketchFrame } from '@amcax/base';
import { ctx2 } from '@app-cad/module';
import {
  BufferAttribute,
  BufferGeometry,
  DoubleSide,
  MeshBasicMaterial,
  Object3D,
  Vector3,
} from 'three-legacy';

export type ArrowMeshAttrs = {
  id?: string;
  sketchFrame?: SketchFrame;
  position?: Vector3;
  points?: Vector3[];
  arrowVec?: Vector3;
  color?: number;
  isReversTaking?: boolean; // 是否反向取点
};
const arrowRotate = Math.PI / 18;
// 旋转轴
const arrowAxis = new Vector3(0, 0, 1);
export class ArrowMesh {
  scene: Object3D;
  sketchFrame: SketchFrame;
  arrowMesh: CSMesh;
  angle: number = 0;
  position?: Vector3; // 世界坐标
  keepSizeGroup: KeepSizeObject3D;
  arrowVec?: Vector3;
  isReversTaking: boolean = false;
  constructor(attrs: ArrowMeshAttrs) {
    this.init(attrs);
    this.keepSizeGroup = new KeepSizeObject3D(ctx2.viewer.sceneSetup.camera);
    this.keepSizeGroup.renderOrder = 1000;
  }
  init(attrs: ArrowMeshAttrs) {
    this.arrowVec = attrs?.arrowVec?.normalize().setLength(1) || null;
    this.sketchFrame = attrs.sketchFrame;
    this.position = attrs.position;
    const material = new MeshBasicMaterial({
      side: DoubleSide,
      transparent: true,
      opacity: 1,
      depthTest: false, // 不进行深度测试
      color: attrs.color || '#1f1f1f',
    });
    // 创建几何体（平面）
    const geometry = new BufferGeometry();
    const mesh = new CSMesh({
      geometry,
      material,
      modelDxid: attrs.id,
    });
    mesh.setRenderOrder(1000);
    this.arrowMesh = mesh;
    this.setVertexs(attrs.points);
  }
  setColor(color: number) {
    this.arrowMesh.setColor(color);
  }
  setVertexs([point3, point4]: Vector3[] = [null, null]) {
    let vec = null;
    if (point3 && point4) {
      vec = new Vector3().subVectors(point4, point3).normalize().setLength(1);
    } else if (this.arrowVec) {
      vec = this.arrowVec?.clone();
    } else {
      return null;
    }
    if (this.isReversTaking) {
      vec.negate();
    }
    const p1 = new Vector3(0, 0, 0);
    const vec2 = vec.clone().applyAxisAngle(arrowAxis, arrowRotate);
    const vec3 = vec.clone().applyAxisAngle(arrowAxis, -arrowRotate);
    const [p2, p3] = [vec2, vec3].map((v) => {
      return this.sketchFrame.toWorld(v).sub(this.sketchFrame.toWorld(p1));
    });
    const vertices = new Float32Array([
      ...p1.toArray(),
      ...p2.toArray(),
      ...p3.toArray(),
    ]);
    this.arrowMesh.geometry.setAttribute(
      'position',
      new BufferAttribute(vertices, 3),
    );
  }
  update(attrs: ArrowMeshAttrs) {
    this.arrowVec = attrs?.arrowVec?.normalize().setLength(1) || null;
    this.position = attrs.position;
    this.isReversTaking = attrs.isReversTaking || false;
    this.setVertexs(attrs.points);
    this.setPosition();
  }
  setPosition() {
    if (this.position) {
      this.keepSizeGroup.position.copy(this.sketchFrame.toWorld(this.position));
    }
  }
  addTo(scene) {
    this.scene = scene;
    this.arrowMesh.addTo(this.keepSizeGroup);
    scene.add(this.keepSizeGroup);
    this.setPosition();
  }
  destroy() {
    this.scene.remove(this.keepSizeGroup);
    this.arrowMesh.destroy();
    this.keepSizeGroup.clear();
  }
}
